<template>
  <div class="image-editor">
    <div class="canvas-container">
      <canvas ref="mainCanvas" :width="canvasWidth" :height="canvasHeight"
      :style="{ width: canvasDisplayWidth + 'px', height: canvasDisplayHeight + 'px' }">
    </canvas>
    </div>

    <div class="controls" style="width: -webkit-fill-available;">

      <div style="display: flex; flex-wrap: wrap; margin-left: 22rpx;justify-content: space-around;">
        <button class="btn" @click="rotateImage(90)">旋转</button>
        <button class="btn" @click="applyFilter('grayscale')">黑白</button>
        <button class="btn" @click="toggleUpDown">上下翻转</button>
        <button class="btn" @click="toggleLeftRight">左右翻转</button>
      </div>

      <div style="display: flex; flex-wrap: wrap; margin-left: 22rpx;justify-content: space-around;">
        <button class="btn" @click="zoomOut">缩小</button>
        <button class="btn" @click="zoomIn">放大</button>
        <button class="btn" @click="toggleGrid">线稿</button>
        <button class="btn" @click="resetImage">原图</button>
      </div>

    </div>
    <div class="controls" style=" margin: 18px 10px;padding-top: 1px;width: -webkit-fill-available;">
       <div class="flex justify-around">
        <button class="btn2" @click="importImage">相册导入</button>
        <!-- <button class="btn2" @click="saveImage">保存相册</button> -->
      </div>
      <div class="flex justify-around">
        <button :class="['btn2', { sending: isSending }]" @click="sendToProjection" :disabled="isSending">开始投图（直投）</button>
        <button :class="['btn2', { sending: isSending1 }]" @click="sendToFourScreens"
          :disabled="isSending">校正投图（侧投）</button>
      </div>
    </div>

    <input type="file" ref="fileInput" accept="image/*" style="display: none;" @change="onFileSelected" />


     <!-- Toast组件 -->
    <div class="toast-container" v-if="toast.show">
      <div class="toast" :class="toast.type">
        {{ toast.message }}
      </div>
    </div>

  </div>
</template>

<script>

export default {
  name: 'ImageEditor',
  data() {
    return {
      // Canvas相关
      canvasWidth: 1280,
      canvasHeight: 720,
      mainCtx: null,
      isSending: false,
      isSending1: false, // 添加isSending1变量
      deviceIP: '192.168.68.1', // 设备IP地址，可以从配置中获取或通过用户输入设置
      // 图片相关
      imageLoaded: false,
      originalImage: null,
      currentImage: null,

      // 变换相关
      rotation: 0,
      scale: 1,
      translateX: 0,
      translateY: 0,
      flipHorizontal: false,
      flipVertical: false,
      // 滤镜相关
      currentFilter: null,

      // 投影相关
      showProjectionModal: false,
      projectionCtx: null,

      // 触摸相关
      isDragging: false,
      lastTouchX: 0,
      lastTouchY: 0,
      startDistance: 0,
      initialScale: 1,

      // Toast相关
      toast: {
        show: false,
        message: '',
        type: 'info', // 可以是 'info', 'success', 'warning', 'error'
        timeout: null
      }
    };
  },
beforeDestroy() {
	// 移除窗口大小变化监听
	window.removeEventListener('resize', this.handleResize);
	
	// 移除Canvas触摸事件监听
	const canvas = this.$refs.mainCanvas;
	if (canvas) {
	  canvas.removeEventListener('touchstart', this.handleTouchStart);
	  canvas.removeEventListener('touchmove', this.handleTouchMove);
	  canvas.removeEventListener('touchend', this.handleTouchEnd);
	}
},
computed: {
	canvasDisplayWidth() {
		// 获取当前视口宽度
		const viewportWidth = Math.min(window.innerWidth, this.canvasWidth);
		// 如果视口宽度小于Canvas宽度，按比例缩放
		if (viewportWidth < this.canvasWidth) {
			return viewportWidth; // 留出一些边距
		}
		return this.canvasWidth;
	},
	canvasDisplayHeight() {
		// 保持宽高比
		const ratio = this.canvasHeight / this.canvasWidth;
		return this.canvasDisplayWidth * ratio;
	}
},
  mounted() {
    document.title = '影描';
    this.initCanvas();
    
    // 添加Canvas触摸事件监听
    const canvas = this.$refs.mainCanvas;
    if (canvas) {
      canvas.addEventListener('touchstart', this.handleTouchStart, { passive: false });
      canvas.addEventListener('touchmove', this.handleTouchMove, { passive: false });
      canvas.addEventListener('touchend', this.handleTouchEnd, { passive: false });
    }
    
    // 禁用双击放大
    document.addEventListener('touchstart', function (event) {
      if (event.touches.length > 1) {
        event.preventDefault();
      }
    }, { passive: false });
    window.addEventListener('resize', this.handleResize);
    let lastTouchEnd = 0;
    document.addEventListener('touchend', function (event) {
      const now = Date.now();
      if (now - lastTouchEnd < 300) {
        event.preventDefault();
      }
      lastTouchEnd = now;
    }, { passive: false });

    // 从localStorage恢复图片
    const imageUrl = localStorage.getItem('correctionImage');
    if (imageUrl) {
      this.createImageObject(imageUrl)
        .then(img => {
          this.originalImage = img;
          this.currentImage = img;
          this.imageLoaded = true;
          
          // 恢复旋转角度
          const savedRotation = localStorage.getItem('imageRotation');
          if (savedRotation) {
            this.rotation = parseInt(savedRotation);
          }
          
          // 绘制图片
          this.drawImageToCanvas();
        })
        .catch(error => {
          console.error('加载图片失败:', error);
          // this.showToast('加载图片失败', 'error');
        });
    }
  },

  methods: {
    // 添加Toast方法
    showToast(message, type = 'info', duration = 2000) {
      // 清除之前的定时器
      if (this.toast.timeout) {
        clearTimeout(this.toast.timeout);
      }
      
      // 设置新的Toast
      this.toast.message = message;
      this.toast.type = type;
      this.toast.show = true;
      
      // 设置自动隐藏
      this.toast.timeout = setTimeout(() => {
        // 添加一个监听器来处理动画结束事件
        const toastElement = document.querySelector('.toast');
        if (toastElement) {
          toastElement.addEventListener('animationend', (e) => {
            // 只有当是fadeOut动画结束时才隐藏元素
            if (e.animationName === 'fadeOut') {
              this.toast.show = false;
            }
          }, { once: true });
          
          // 添加一个类来触发淡出动画
          toastElement.classList.add('toast-hiding');
        } else {
          // 如果找不到元素，直接隐藏
          this.toast.show = false;
        }
      }, duration - 300); // 提前300ms开始准备动画
    },
    /**
     * 初始化Canvas
     */
    initCanvas() {
      try {
        const canvas = this.$refs.mainCanvas;
        if (!canvas) {
          console.error('无法获取Canvas元素');
          return;
        }

        this.mainCtx = canvas.getContext('2d');
        if (!this.mainCtx) {
          console.error('无法获取Canvas上下文');
          return;
        }

        console.log('Canvas初始化完成');
      } catch (error) {
        console.error('初始化Canvas失败:', error);
      }
    },

    /**
     * 导入图片
     */
    importImage() {
      this.$refs.fileInput.click();
    },

    /**
     * 文件选择处理
     */
    onFileSelected(event) {
      const file = event.target.files[0];
      if (!file) return;

      const reader = new FileReader();
      reader.onload = (e) => {
        this.createImageObject(e.target.result)
          .then(img => {
            this.originalImage = img;
            this.currentImage = img;
            this.imageLoaded = true;

            // 重置变换
            this.resetImage();
          })
          .catch(error => {
            console.error('加载图片失败:', error);
            this.showToast('加载图片失败', 'error');
          });
      };
      reader.readAsDataURL(file);
    },

    /**
     * 创建图片对象
     */
    createImageObject(src) {
      return new Promise((resolve, reject) => {
        const img = new Image();
        img.crossOrigin = 'anonymous'; // 允许跨域加载图片
        img.onload = () => {
          console.log('图片加载成功:', img.width, 'x', img.height);
          resolve(img);
        };
        img.onerror = (e) => {
          console.error('图片加载失败:', e);
          reject(new Error('图片加载失败'));
        };
        img.src = src;
      });
    },
    /**
 * 发送图像到四角校正页面
 */
    sendToFourScreens1() {
      if (this.isSending) return;
      this.isSending = true;
      this.isSending1 = true;

      if (!this.imageLoaded) {
        this.showToast('请先加载图片！', 'error');
        this.isSending = false;
        this.isSending1 = false;
        return;
      }
      try {
        // 获取Canvas图像数据
        const canvas = this.$refs.mainCanvas;
        // 将Canvas转换为JPG格式的Blob
        canvas.toBlob((blob) => {
          // 创建临时URL
          const imageUrl = URL.createObjectURL(blob);
        
          // 将图像数据保存到localStorage，以便在新页面中使用
          localStorage.setItem('correctionImage', imageUrl);
          // 导航到四角校正页面
          // 使用事件触发页面切换，而不是改变URL
          this.$emit('navigate', 'correction');

          // 2秒后重置状态
          setTimeout(() => {
            this.isSending = false;
            this.isSending1 = false;
            console.log("Sending enabled again.");
          }, 2000);
        }, 'image/jpeg', 0.9);
      } catch (error) {
        console.error('准备图片数据失败:', error);
        this.showToast('发送失败，请重试', 'error');
        this.isSending = false;
        this.isSending1 = false;
      }
    },
        /**
     * 发送图像到四角校正页面（优化版本）
     */
    sendToFourScreens() {
      if (this.isSending) return;
      this.isSending = true;
      this.isSending1 = true;

      if (!this.imageLoaded) {
        this.showToast('请先加载图片！', 'error');
        this.isSending = false;
        this.isSending1 = false;
        return;
      }

      try {
          // 计算图片在Canvas中的实际位置和尺寸
        const imgWidth = this.currentImage.width;
        const imgHeight = this.currentImage.height;
        const ratio = Math.min(this.canvasWidth / imgWidth, this.canvasHeight / imgHeight);
        const scaledWidth = imgWidth * ratio;
        const scaledHeight = imgHeight * ratio;

        // 根据旋转角度确定实际显示尺寸
        const isRotated90or270 = this.rotation % 180 !== 0;
        
        // 创建一个离屏Canvas，尺寸需要根据旋转角度调整
        const offCanvas = document.createElement('canvas');
        if (isRotated90or270) {
          // 旋转90或270度时，宽高需要互换
          offCanvas.width = scaledHeight;
          offCanvas.height = scaledWidth;
        } else {
          offCanvas.width = scaledWidth;
          offCanvas.height = scaledHeight;
        }
        const offCtx = offCanvas.getContext('2d');

        // 在离屏Canvas上绘制图片，应用所有变换
        offCtx.save();
        offCtx.translate(offCanvas.width / 2, offCanvas.height / 2);
        offCtx.rotate((this.rotation * Math.PI) / 180);
        offCtx.scale(
          this.flipHorizontal ? -1 : 1,
          this.flipVertical ? -1 : 1
        );

        // 绘制图片（居中）
        offCtx.drawImage(
          this.currentImage,
          -scaledWidth / 2,
          -scaledHeight / 2,
          scaledWidth,
          scaledHeight
        );

        // 应用滤镜
          if (this.currentFilter) {
            if (this.currentFilter === 'lineart') {
              // 应用线稿效果
              const imageData = offCtx.getImageData(0, 0, offCanvas.width, offCanvas.height);
              // 使用detectEdges方法处理图像数据
              const edgeData = this.detectEdges(imageData, offCanvas.width, offCanvas.height);
              // 将处理后的图像数据放回Canvas
              offCtx.putImageData(edgeData, 0, 0);
            } else {
              const imageData = offCtx.getImageData(0, 0, offCanvas.width, offCanvas.height);
              const data = imageData.data;

              // 应用滤镜
              switch (this.currentFilter) {
                case 'grayscale':
                  // 灰度滤镜
                  for (let i = 0; i < data.length; i += 4) {
                    const avg = (data[i] + data[i + 1] + data[i + 2]) / 3;
                    data[i] = avg; // 红
                    data[i + 1] = avg; // 绿
                    data[i + 2] = avg; // 蓝
                  }
                  break;

                case 'sepia':
                  // 复古滤镜
                  for (let i = 0; i < data.length; i += 4) {
                    const r = data[i];
                    const g = data[i + 1];
                    const b = data[i + 2];

                    data[i] = Math.min(255, (r * 0.393) + (g * 0.769) + (b * 0.189));
                    data[i + 1] = Math.min(255, (r * 0.349) + (g * 0.686) + (b * 0.168));
                    data[i + 2] = Math.min(255, (r * 0.272) + (g * 0.534) + (b * 0.131));
                  }
                  break;

                case 'invert':
                  // 反色滤镜
                  for (let i = 0; i < data.length; i += 4) {
                    data[i] = 255 - data[i]; // 红
                    data[i + 1] = 255 - data[i + 1]; // 绿
                    data[i + 2] = 255 - data[i + 2]; // 蓝
                  }
                  break;
              }

              // 将处理后的图像数据放回Canvas
              offCtx.putImageData(imageData, 0, 0);
            }
          }

        offCtx.restore();

        // 将离屏Canvas转换为JPG格式的Blob
        offCanvas.toBlob((blob) => {
          // 创建临时URL
          const imageUrl = URL.createObjectURL(blob);
           // 保存旋转角度
          localStorage.setItem('imageRotation', this.rotation);
          // 将图像数据保存到localStorage，以便在新页面中使用
          localStorage.setItem('correctionImage', imageUrl);
          
          // 导航到四角校正页面
          this.$emit('navigate', 'correction');
          

          // 2秒后重置状态
          setTimeout(() => {
            this.isSending = false;
            this.isSending1 = false;
            console.log("Sending enabled again.");
          }, 2000);
        }, 'image/jpeg', 0.9);
      } catch (error) {
        console.error('准备图片数据失败:', error);
        this.showToast('发送失败，请重试', 'error');
        this.isSending = false;
        this.isSending1 = false;
      }
    },
    /**
     * 应用滤镜
     */
    applyFilter(filterType) {
      if (!this.imageLoaded) {
        this.showToast('请先加载图片！', 'error');
        this.isSending = false;
        return;
      }
      this.currentFilter = filterType;
      
  

      
      this.drawImageToCanvas();
    },

    /**
     * 将滤镜应用到Canvas
     */
    applyFilterToCanvas() {
      if (!this.mainCtx || !this.currentFilter) return;

      try {
        // 获取图像数据
        const imageData = this.mainCtx.getImageData(0, 0, this.canvasWidth, this.canvasHeight);
        const data = imageData.data;

        // 应用滤镜
        switch (this.currentFilter) {
          case 'grayscale':
            // 灰度滤镜
            for (let i = 0; i < data.length; i += 4) {
              const avg = (data[i] + data[i + 1] + data[i + 2]) / 3;
              data[i] = avg; // 红
              data[i + 1] = avg; // 绿
              data[i + 2] = avg; // 蓝
            }
            break;

          case 'sepia':
            // 复古滤镜
            for (let i = 0; i < data.length; i += 4) {
              const r = data[i];
              const g = data[i + 1];
              const b = data[i + 2];

              data[i] = Math.min(255, (r * 0.393) + (g * 0.769) + (b * 0.189));
              data[i + 1] = Math.min(255, (r * 0.349) + (g * 0.686) + (b * 0.168));
              data[i + 2] = Math.min(255, (r * 0.272) + (g * 0.534) + (b * 0.131));
            }
            break;

          case 'invert':
            // 反色滤镜
            for (let i = 0; i < data.length; i += 4) {
              data[i] = 255 - data[i]; // 红
              data[i + 1] = 255 - data[i + 1]; // 绿
              data[i + 2] = 255 - data[i + 2]; // 蓝
            }
            break;
        }

        // 将处理后的图像数据放回Canvas
        this.mainCtx.putImageData(imageData, 0, 0);
      } catch (error) {
        console.error('应用滤镜失败:', error);
      }
    },

    /**
     * 旋转图片
     */
    rotateImage(degrees) {
      if (!this.imageLoaded) return;

      // 更新旋转角度
      this.rotation = (this.rotation + degrees) % 360;

      // 重新绘制图片
      this.drawImageToCanvas();
    },

    /**
     * 打开投影模态框
     */
    projectImage() {
      if (!this.imageLoaded) return;

      this.showProjectionModal = true;

      // 在下一个DOM更新周期初始化投影Canvas
      this.$nextTick(() => {
        const projCanvas = this.$refs.projectionCanvas;
        if (!projCanvas) return;

        this.projectionCtx = projCanvas.getContext('2d');

        // 复制主Canvas的内容到投影Canvas
        this.projectionCtx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
        this.projectionCtx.drawImage(this.$refs.mainCanvas, 0, 0);
      });
    },

    /**
     * 关闭投影模态框
     */
    closeProjection() {
      this.showProjectionModal = false;
    },
    sendToProjection() {
      if (this.isSending) return;
      this.isSending = true;

      if (!this.imageLoaded) {
        this.showToast('请先加载图片！', 'error');
        this.isSending = false;
        return;
      }
      try {
        // 获取Canvas图像数据
        const canvas = this.$refs.mainCanvas;

        // 使用toDataURL替代toBlob，解决移动端兼容性问题
        const dataURL = canvas.toDataURL('image/jpeg', 0.9);
        // 将base64转换为Blob
        const base64ToBlob = (dataURL) => {
          const arr = dataURL.split(',');
          const mime = arr[0].match(/:(.*?);/)[1];
          const bstr = atob(arr[1]);
          let n = bstr.length;
          const u8arr = new Uint8Array(n);
          while (n--) {
            u8arr[n] = bstr.charCodeAt(n);
          }
          return new Blob([u8arr], { type: mime });
        };

        const blob = base64ToBlob(dataURL);

        // 创建FormData
        const formData = new FormData();
        formData.append('file', blob, 'image.jpg'); // 修改文件名为.jpg

        // 使用相对路径，不依赖特定IP
        // fetch('http://192.168.3.218/playimg', {
        fetch(`/playimg`, {          method: 'POST',
          body: formData
        })
            .then(response => {
              if (!response.ok) {
                throw new Error(`HTTP错误，状态码: ${response.status}`);
              }
              return response.json();
            })
            .then(data => {
              console.log(data);
              this.showToast('图片已成功发送到投影设备！', 'success');
              this.closeProjection();
            })
            .catch(error => {
              console.error('上传失败', error);
              if (error.message && error.message.includes('net::ERR_CONNECTION')) {
                console.log('网络连接问题，请检查网络连接');
                this.showToast('网络连接问题，请检查网络连接', 'error');
              } else if (error.message && error.message.includes('404')) {
                console.log('服务器未找到上传地址');
                this.showToast('服务器未找到上传地址', 'error');
              } else {
                console.log('其他错误：', error);
                this.showToast('发送失败，请重试', 'error');
              }
            })
            .finally(() => {
              setTimeout(() => {
                this.isSending = false; // 2秒后重新启用按钮
                console.log("Sending enabled again.");
              }, 1000);
            });
      } catch (error) {
        console.error('准备图片数据失败:', error);
        this.showToast('发送失败，请重试', 'error');
        this.isSending = false;
      }
    }
    ,
    sendToProjection1() {
      if (this.isSending) return;
      this.isSending = true;

      try {
        // 获取Canvas图像数据
        const canvas = this.$refs.mainCanvas;

        // 将Canvas转换为JPG格式的Blob
        canvas.toBlob((blob) => {
          const devip = this.deviceIP;
          console.log('http://' + devip + '/playimg');

          // 创建FormData
          const formData = new FormData();
          formData.append('file', blob, 'image.jpg'); // 修改文件名为.jpg
          formData.append('user', 'test');

          // 使用fetch API上传
          fetch('http://' + devip + '/playimg', {
            method: 'POST',
            body: formData
          })
            .then(response => {
              if (!response.ok) {
                throw new Error(`HTTP错误，状态码: ${response.status}`);
              }
              return response.json();
            })
            .then(data => {
              console.log(data);
              this.showToast('图片已成功发送到投影设备！', 'success');
              this.closeProjection();
            })
            .catch(error => {
              console.error('上传失败', error);
              if (error.message && error.message.includes('net::ERR_CONNECTION')) {
                console.log('网络连接问题，请检查网络连接');
                this.showToast('网络连接问题，请检查网络连接', 'error');
              } else if (error.message && error.message.includes('404')) {
                console.log('服务器未找到上传地址');
                this.showToast('服务器未找到上传地址', 'error');
              } else {
                console.log('其他错误：', error);
                this.showToast('发送失败，请重试', 'error');
              }
            })
            .finally(() => {
              this.isSending = false;
            });
        }, 'image/jpeg', 0.9); // 修改为JPEG格式，质量为0.9
      } catch (error) {
        console.error('准备图片数据失败:', error);
        this.showToast('发送失败，请重试', 'error');
        this.isSending = false;
      }
    },
    saveImage() {
      if (!this.imageLoaded) return;

      try {
        const canvas = this.$refs.mainCanvas;
        const dataURL = canvas.toDataURL('image/jpeg', 0.9);

        // 创建一个临时链接并触发下载
        const link = document.createElement('a');
        link.href = dataURL;
        link.download = 'edited-image.jpg';
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
        this.showToast('图片已保存', 'success');
      } catch (error) {
        console.error('保存图片失败:', error);
        this.showToast('保存图片失败', 'error');
      }
    },

    /**
     * 上下翻转
     */
    toggleUpDown() {
      if (!this.imageLoaded) return;

      this.flipVertical = !this.flipVertical;
      this.drawImageToCanvas();
    },

    /**
     * 左右翻转
     */
    toggleLeftRight() {
      if (!this.imageLoaded) return;

      this.flipHorizontal = !this.flipHorizontal;
      this.drawImageToCanvas();
    },

    /**
     * 缩小图片
     */
    zoomOut() {
      if (!this.imageLoaded) return;

      this.scale = Math.max(0.1, this.scale - 0.1);
      this.drawImageToCanvas();
    },

    /**
     * 放大图片
     */
    zoomIn() {
      if (!this.imageLoaded) return;

      this.scale = Math.min(3, this.scale + 0.1);
      this.drawImageToCanvas();
    },

    /**
     * 切换网格线显示
     */
    toggleGrid() {
      if (!this.imageLoaded) return;

      if (this.currentFilter !== 'lineart') {
        this.currentFilter = 'lineart';
        this.applyLineArtEffect();
      } else {
        this.currentFilter = null;
        this.drawImageToCanvas();
      }
    },
    drawImageToCanvas() {
      if (!this.imageLoaded || !this.currentImage || !this.mainCtx) {
        console.log('无法绘制图片:', {
          imageLoaded: this.imageLoaded,
          hasCurrentImage: !!this.currentImage,
          hasMainCtx: !!this.mainCtx
        });
        return;
      }

      try {
        // 清除Canvas
        this.mainCtx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);

        console.log('绘制图片:', {
          imgWidth: this.currentImage.width,
          imgHeight: this.currentImage.height,
          canvasWidth: this.canvasWidth,
          canvasHeight: this.canvasHeight,
          scale: this.scale,
          rotation: this.rotation,
          flipH: this.flipHorizontal,
          flipV: this.flipVertical
        });

        // 保存当前状态
        this.mainCtx.save();

        // 移动到Canvas中心
        this.mainCtx.translate(this.canvasWidth / 2 + this.translateX, this.canvasHeight / 2 + this.translateY);

        // 旋转
        this.mainCtx.rotate((this.rotation * Math.PI) / 180);

        // 计算图片绘制尺寸和位置
        const imgWidth = this.currentImage.width;
        const imgHeight = this.currentImage.height;
        
        // 根据旋转角度计算适合的缩放比例
        let ratio;
        const normalizedRotation = ((this.rotation % 360) + 360) % 360; // 标准化旋转角度到0-359
        
        if (normalizedRotation === 90 || normalizedRotation === 270) {
          // 旋转90度或270度时，宽高需要互换来计算缩放比例
          ratio = Math.min(this.canvasWidth / imgHeight, this.canvasHeight / imgWidth);
        } else {
          // 旋转0度或180度时，正常计算缩放比例
          ratio = Math.min(this.canvasWidth / imgWidth, this.canvasHeight / imgHeight);
        }
        
        // 应用用户手动设置的缩放
        const finalScale = ratio * this.scale;
        
        // 翻转
        this.mainCtx.scale(
          this.flipHorizontal ? -finalScale : finalScale,
          this.flipVertical ? -finalScale : finalScale
        );

        // 计算最终绘制尺寸
        const scaledWidth = imgWidth;
        const scaledHeight = imgHeight;

        // 绘制图片（居中）
        this.mainCtx.drawImage(
          this.currentImage,
          -scaledWidth / 2,
          -scaledHeight / 2,
          scaledWidth,
          scaledHeight
        );

        // 应用滤镜
        if (this.currentFilter) {
          if (this.currentFilter === 'lineart') {
            // 恢复状态以便应用线稿效果
            this.mainCtx.restore();
            this.applyLineArtEffect();
            return; // 提前返回，因为applyLineArtEffect已经完成了所有绘制
          } else {
            this.applyFilterToCanvas();
          }
        }

      

        // 恢复状态
        this.mainCtx.restore();

        console.log('Canvas 绘制完成');
      } catch (error) {
        console.error('绘制图片失败:', error);
      }
    },
    /**
     * 应用线稿效果
     */
    applyLineArtEffect() {
      if (!this.imageLoaded || !this.currentImage || !this.mainCtx) return;

      try {
        // 清除Canvas
        this.mainCtx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);

        // 保存当前状态
        this.mainCtx.save();

        // 移动到Canvas中心
        this.mainCtx.translate(this.canvasWidth / 2 + this.translateX, this.canvasHeight / 2 + this.translateY);

        // 旋转
        this.mainCtx.rotate((this.rotation * Math.PI) / 180);

        // 处理翻转
        this.mainCtx.scale(
          this.flipHorizontal ? -this.scale : this.scale,
          this.flipVertical ? -this.scale : this.scale
        );

        // 计算图片绘制尺寸和位置
        const imgWidth = this.currentImage.width;
        const imgHeight = this.currentImage.height;

        // 根据旋转角度计算适合的缩放比例
        let ratio;
        const normalizedRotation = ((this.rotation % 360) + 360) % 360; // 标准化旋转角度到0-359
        
        if (normalizedRotation === 90 || normalizedRotation === 270) {
          // 旋转90度或270度时，宽高需要互换来计算缩放比例
          ratio = Math.min(this.canvasWidth / imgHeight, this.canvasHeight / imgWidth);
        } else {
          // 旋转0度或180度时，正常计算缩放比例
          ratio = Math.min(this.canvasWidth / imgWidth, this.canvasHeight / imgHeight);
        }
        
        // 应用用户手动设置的缩放
        const finalScale = ratio * this.scale;
        const scaledWidth = imgWidth * ratio;
        const scaledHeight = imgHeight * ratio;

        // 限制处理的图像尺寸，避免处理过大的图像
        const MAX_DIMENSION = 800; // 降低最大处理尺寸以减少内存使用
        let processingWidth = scaledWidth;
        let processingHeight = scaledHeight;
        let processingScale = 1;
        
        if (scaledWidth > MAX_DIMENSION || scaledHeight > MAX_DIMENSION) {
          processingScale = Math.min(MAX_DIMENSION / scaledWidth, MAX_DIMENSION / scaledHeight);
          processingWidth = Math.floor(scaledWidth * processingScale);
          processingHeight = Math.floor(scaledHeight * processingScale);
        }

        // 确保尺寸是有效的正整数
        processingWidth = Math.max(1, Math.floor(processingWidth));
        processingHeight = Math.max(1, Math.floor(processingHeight));

        // 创建临时Canvas用于处理图像
        const tempCanvas = document.createElement('canvas');
        tempCanvas.width = processingWidth;
        tempCanvas.height = processingHeight;
        const tempCtx = tempCanvas.getContext('2d');

        // 在临时Canvas上绘制原始图像
        tempCtx.drawImage(
          this.currentImage,
          0,
          0,
          processingWidth,
          processingHeight
        );

        // 获取图像数据
        const imageData = tempCtx.getImageData(0, 0, processingWidth, processingHeight);

        // 应用边缘检测算法（Sobel算子）
        const edgeData = this.detectEdges(imageData, processingWidth, processingHeight);

        // 将处理后的图像数据放回临时Canvas
        tempCtx.putImageData(edgeData, 0, 0);

        // 将临时Canvas的内容绘制到主Canvas
        this.mainCtx.drawImage(
          tempCanvas,
          -scaledWidth / 2,
          -scaledHeight / 2,
          scaledWidth,
          scaledHeight
        );

        // 恢复状态
        this.mainCtx.restore();

        console.log('线稿效果应用完成');
      } catch (error) {
        console.error('应用线稿效果失败:', error);
        // 出错时恢复原图
        this.currentFilter = null;
        this.showGrid = false; // 确保重置showGrid状态
        this.drawImageToCanvas();
        
        // 添加用户提示
        this.showToast('图片太大，无法应用线稿效果，请尝试缩小图片后再试', 'error');
      }
    },

    /**
     * 边缘检测算法
     */
    detectEdges(imageData, width, height) {
      const data = imageData.data;
      const output = new ImageData(width, height);
      const outputData = output.data;

      // 初始化输出为白色背景
      for (let i = 0; i < outputData.length; i += 4) {
        outputData[i] = 255;     // R
        outputData[i + 1] = 255; // G
        outputData[i + 2] = 255; // B
        outputData[i + 3] = 255; // A
      }

      // 首先转换为灰度图
      for (let i = 0; i < data.length; i += 4) {
        const r = data[i];
        const g = data[i + 1];
        const b = data[i + 2];
        // 灰度转换公式：0.299*R + 0.587*G + 0.114*B
        const gray = 0.299 * r + 0.587 * g + 0.114 * b;
        data[i] = data[i + 1] = data[i + 2] = gray;
      }

      // Sobel算子
      const sobelX = [-1, 0, 1, -2, 0, 2, -1, 0, 1];
      const sobelY = [-1, -2, -1, 0, 0, 0, 1, 2, 1];

      // 在一次遍历中计算梯度幅值和最大值
      let sumMagnitude = 0;
      let maxMagnitude = 0;
      let pixelCount = 0;
      
      // 不再预先创建magnitudes数组，而是使用二维数组按需创建
      const magnitudes = [];
      for (let y = 0; y < height - 2; y++) {
        magnitudes[y] = new Array(width - 2).fill(0);
      }

      try {
        // 第一遍：计算所有梯度幅值和统计信息
        for (let y = 1; y < height - 1; y++) {
          for (let x = 1; x < width - 1; x++) {
            let pixelX = 0;
            let pixelY = 0;

            // 应用3x3卷积核
            for (let ky = -1; ky <= 1; ky++) {
              for (let kx = -1; kx <= 1; kx++) {
                const idx = ((y + ky) * width + (x + kx)) * 4;
                const kernelIdx = (ky + 1) * 3 + (kx + 1);

                pixelX += data[idx] * sobelX[kernelIdx];
                pixelY += data[idx] * sobelY[kernelIdx];
              }
            }

            // 计算梯度幅值
            const magnitude = Math.sqrt(pixelX * pixelX + pixelY * pixelY);
            
            // 存储梯度幅值
            magnitudes[y - 1][x - 1] = magnitude;
            
            // 更新统计信息
            sumMagnitude += magnitude;
            maxMagnitude = Math.max(maxMagnitude, magnitude);
            pixelCount++;
          }
        }

        // 计算平均梯度幅值
        const avgMagnitude = sumMagnitude / pixelCount;
        
        // 设置动态阈值，根据图像特性调整
        const threshold = avgMagnitude * 0.5;
        
        // 第二遍：应用阈值和增强对比度
        for (let y = 1; y < height - 1; y++) {
          for (let x = 1; x < width - 1; x++) {
            const magnitude = magnitudes[y - 1][x - 1];
            const outIdx = (y * width + x) * 4;
            
            // 应用阈值，只有超过阈值的边缘才会被显示
            if (magnitude > threshold) {
              // 增强对比度，确保边缘更加清晰
              const edgeStrength = Math.min(255, (magnitude / maxMagnitude) * 255);
              const edgeValue = 255 - edgeStrength;
              
              outputData[outIdx] = edgeValue;
              outputData[outIdx + 1] = edgeValue;
              outputData[outIdx + 2] = edgeValue;
            }
            // 低于阈值的像素保持白色背景（已在初始化时设置）
          }
        }
      } catch (error) {
        console.error('边缘检测算法出错:', error);
        // 出错时返回原始图像数据的副本
        const fallbackOutput = new ImageData(width, height);
        for (let i = 0; i < data.length; i++) {
          fallbackOutput.data[i] = data[i];
        }
        return fallbackOutput;
      }

      return output;
    },
   

    // 重置图片时也重置翻转状态
    resetImage() {
      if (!this.imageLoaded) return;

      // 重置变换参数
      this.rotation = 0;
      this.scale = 1;
      this.translateX = 0;
      this.translateY = 0;
      this.currentFilter = null;
      this.flipHorizontal = false;
      this.flipVertical = false;

      // 重新绘制图片
      this.drawImageToCanvas();
    },
    
    /**
     * 处理触摸开始事件
     */
    handleTouchStart(event) {
      event.preventDefault();
      
      if (!this.imageLoaded) return;
      
      const touches = event.touches;
      
      if (touches.length === 1) {
        // 单指触摸 - 准备拖动
        this.isDragging = true;
        this.lastTouchX = touches[0].clientX;
        this.lastTouchY = touches[0].clientY;
      } else if (touches.length === 2) {
        // 双指触摸 - 准备缩放
        this.isDragging = false;
        
        // 计算两个触摸点之间的初始距离
        const dx = touches[0].clientX - touches[1].clientX;
        const dy = touches[0].clientY - touches[1].clientY;
        this.startDistance = Math.sqrt(dx * dx + dy * dy);
        this.initialScale = this.scale;
      }
    },
    
    /**
     * 处理触摸移动事件
     */
    handleTouchMove(event) {
      event.preventDefault();
      
      if (!this.imageLoaded) return;
      
      const touches = event.touches;
      
      if (this.isDragging && touches.length === 1) {
        // 单指拖动 - 移动图像
        const currentX = touches[0].clientX;
        const currentY = touches[0].clientY;
        
        // 计算移动距离
        const deltaX = currentX - this.lastTouchX;
        const deltaY = currentY - this.lastTouchY;
        
        // 更新图像位置
        this.translateX += deltaX;
        this.translateY += deltaY;
        
        // 更新最后触摸位置
        this.lastTouchX = currentX;
        this.lastTouchY = currentY;
        
        // 重新绘制图像
        this.drawImageToCanvas();
      } else if (touches.length === 2) {
        // 双指缩放
        const dx = touches[0].clientX - touches[1].clientX;
        const dy = touches[0].clientY - touches[1].clientY;
        const distance = Math.sqrt(dx * dx + dy * dy);
        
        // 计算缩放比例
        const newScale = this.initialScale * (distance / this.startDistance);
        
        // 限制缩放范围
        this.scale = Math.max(0.1, Math.min(3, newScale));
        
        // 重新绘制图像
        this.drawImageToCanvas();
      }
    },
    
    /**
     * 处理触摸结束事件
     */
    handleTouchEnd(event) {
      this.isDragging = false;
    },
    
    /**
     * 处理窗口大小变化
     */
    handleResize() {
      // 重新绘制图像以适应新的窗口大小
      if (this.imageLoaded) {
        this.drawImageToCanvas();
      }
    }
  }
};
</script>

<style>
.image-editor {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin: 0 auto;
  text-align: center;
  width: 100%;
}

.canvas-container {
  margin-bottom: 20px;
  position: relative;
  justify-content: center;
  align-items: center;
  width: 100%;
	overflow-x: auto;
	max-width: 100%;
	display: flex;
}

body {
  display: block;
  margin: 0px !important;
}

canvas {
  display: block;
  background: black;
}

.controls {
  background-color: #efefef;
  border-radius: 10px;
  margin: 0 10px;
}

.button-group {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  margin-bottom: 10px;
  background-color: #efefef;
  border-radius: 20rpx;
  margin: 0 20rpx;
}

button:disabled {
  background-color: #cccccc;
  cursor: not-allowed;
}

button:hover:not(:disabled) {
  background-color: #45a049;
}

.filter-options {
  margin-top: 10px;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
}

.filter-options span {
  margin-right: 10px;
}

.filter-options button {
  margin: 0 5px 5px 0;
  background-color: #2196F3;
}

.filter-options button:hover:not(:disabled) {
  background-color: #0b7dda;
}

/* 投影模态框样式 */
.projection-modal {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.7);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1000;
}

.projection-content {
  background-color: white;
  padding: 20px;
  border-radius: 8px;
  max-width: 80%;
  max-height: 90%;
  overflow: auto;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.projection-preview {
  margin: 15px 0;
  border: 1px solid #ddd;
}

.projection-controls {
  display: flex;
  justify-content: center;
  margin-top: 15px;
}

.projection-controls button {
  margin: 0 10px;
}

.projection-controls button:first-child {
  background-color: #2196F3;
}

.projection-controls button:first-child:hover {
  background-color: #0b7dda;
}

.projection-controls button:last-child {
  background-color: #f44336;
}

.projection-controls button:last-child:hover {
  background-color: #d32f2f;
}
</style>
<style>
html, body {
  touch-action: manipulation;
  -webkit-text-size-adjust: 100%;
  -webkit-tap-highlight-color: rgba(0,0,0,0);
}
.sending {
  color: #fff;
  background-color: red !important;
}

.justify-around {
  justify-content: space-around;
}

.flex {
  display: flex;
}

.btn {
  flex: 1;
  margin: 4px;
  height: 35px;
  background-color: #fff;
  border-radius: 5px;
  border: black 1px solid;
  line-height: 35px;
  font-size: 12px;
  text-align: center;
  word-break: break-word;
}

.connect-box {
  display: flex;
  border: black 1px solid;
  border-radius: 10px;
  height: 35px;
  margin: 8px 25px;
  overflow: hidden;
}

.connect-box-state {
  width: 75px;
  height: 35px;
  line-height: 35px;
  text-align: center;
  background: #f56c6c;
  color: black;
}

.connect-box-x {
  width: 35px;
  height: 35px;
  line-height: 35px;
  text-align: center;
  color: black;
  font-weight: bold;
  border-left: black 1px solid;
  border-right: black 1px solid;
}

.connect-box-select-device {
  flex: 1;
  height: 35px;
  line-height: 35px;
  text-align: center;
  color: black;
}

.btn2 {
  flex: 1;
  margin: 8px;
  height: 40px !important;
  background-color: #fff;
  border-radius: 5px;
  border: black 1px solid;
  line-height: 40px !important;
  font-size: 14px;
  text-align: center;
}

/* Toast样式 */
.toast-container {
  position: fixed;
  top: 20px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 9999;
  pointer-events: none;
}

.toast {
  padding: 10px 20px;
  border-radius: 4px;
  color: white;
  font-size: 14px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
  animation: fadeIn 0.3s;
  white-space: nowrap;
}

.toast.toast-hiding {
  animation: fadeOut 0.3s forwards;
}

.toast.info {
  background-color: #2196F3;
}

.toast.success {
  background-color: #4CAF50;
}

.toast.warning {
  background-color: #FF9800;
}

.toast.error {
  background-color: #F44336;
}

@keyframes fadeIn {
  from { opacity: 0; transform: translateY(-20px); }
  to { opacity: 1; transform: translateY(0); }
}

@keyframes fadeOut {
  from { opacity: 1; transform: translateY(0); }
  to { opacity: 0; transform: translateY(-20px); }
}
</style>